﻿//-----------------------------------------------------------------------
// <copyright file="Rule.cs" company="tuliprules.org">
//     Copyright (c) 2010 tuplelister, tuliprules.org.
// </copyright>
// <summary>This is the Rule class.</summary>
//-----------------------------------------------------------------------

namespace Tulip.Rules
{
    using System;

    /// <summary>
    /// Represents a Tulip rule
    /// </summary>
    public class Rule : IRuleObject
    {
        /// <summary>
        /// A URI used as a type specifer for the rule set.
        /// </summary>
        /// <remarks>
        /// This URI can differen from that of the enclosing rule set in order
        /// to distinguish between different types of rule.  However, in this case,
        /// each URI at the rule level will be associated with the rule set type.
        /// </remarks>
        private readonly Uri type;
        
        /// <summary>
        /// The version specifier for the rule set.
        /// </summary>
        private Version version;

        /// <summary>
        /// Initializes a new instance of the Rule class.
        /// </summary>
        /// <param name="type">
        /// A URI used as a type specifer for the rule set.
        /// </param>
        public Rule(Uri type)
        {
            this.type = type;
        }

        /// <summary>
        /// Initializes a new instance of the Rule class.
        /// </summary>
        /// <param name="type">
        /// A URI used as a type specifer for the rule set.
        /// </param>
        /// <param name="name">
        /// Name of the rule set.
        /// </param>
        public Rule(Uri type, string name)
            : this(type)
        {
            this.Name = name;
        }

        /// <summary>
        /// Initializes a new instance of the Rule class.
        /// </summary>
        /// <param name="type">
        /// A URI used as a type specifer for the rule set.
        /// </param>
        /// <param name="name">
        /// Name of the rule set.
        /// </param>
        /// <param name="majorVersion">
        /// The major version component of the version number.
        /// </param>
        /// <param name="minorVersion">
        /// The minor version component of the version number.
        /// </param>
        /// <param name="build">
        /// The build component of the version number.
        /// </param>
        /// <param name="revision">
        /// The revision component of the version number.
        /// </param>
        public Rule(Uri type, string name, int majorVersion, int minorVersion, int build, int revision) 
            : this(type, name)
        {
            this.MajorVersion = majorVersion;
            this.MinorVersion = minorVersion;
            this.Build = build;
            this.Revision = revision;
        }

        /// <summary>
        /// Initializes a new instance of the Rule class.
        /// </summary>
        /// <param name="type">
        /// A URI used as a type specifer for the rule set.
        /// </param>
        /// <param name="name">
        /// Name of the rule set.
        /// </param>
        /// <param name="version">
        /// The version specifer for the rule set.
        /// </param>
        public Rule(Uri type, string name, Version version)
            : this(type, name)
        {
            this.Version = version;
        }

        /// <summary>
        /// Gets a URI that can be used as a type specifer for the rule set.
        /// </summary>
        /// <value>A URI that can be used as a type specifer for the rule set.</value>
        public Uri Type
        {
            get
            {
                return this.type;
            }
        }

        /// <summary>
        /// Gets or sets the name of the rule.
        /// </summary>
        /// <value>
        /// The name of the rule.
        /// </value>
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets the major version component of the version number.
        /// </summary>
        /// <value>
        /// The major version component of the version number.
        /// </value>
        public int MajorVersion { get; set; }

        /// <summary>
        /// Gets or sets the minor version component of the version number.
        /// </summary>
        /// <value>
        /// The minor version component of the version number.
        /// </value>
        public int MinorVersion { get; set; }

        /// <summary>
        /// Gets or sets the build component of the version number.
        /// </summary>
        /// <value>
        /// The build component of the version number.
        /// </value>
        public int Build { get; set; }

        /// <summary>
        /// Gets or sets the revision component of the version number.
        /// </summary>
        /// <value>
        /// The revision component of the version number.
        /// </value>
        public int Revision { get; set; }

        /// <summary>
        /// Gets the version number.
        /// </summary>
        /// <value>
        /// The version number.
        /// </value>
        public Version Version
        {
            get
            {
                return this.version ??
                       (this.version = new Version(this.MajorVersion, this.MinorVersion, this.Build, this.Revision));
            }

            private set
            {
                this.version = value;
            }
        }
    }
}
